package base.file_io_demo.io_demo01;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.io.Serializable;
import java.util.Date;

/**
 * 以下这些流都是用了 装饰者模式
 * 
 * 数据流演示 :方便处理Java中的8大数据类型数据
 * DataInputStream、DataOutputStream 存储了数据的同时，存储了数据类型。
 * 
 * 对象流演示：对象的序列化和反序列化
 * ObjectInputStream、ObjectOutputStream
 * 
 * 打印流演示：处理流
 * 
 * 注意：工作中基本上使用的都是commons-io 组件。
 *
 */
public class IOTest2 {
	
	public static void main(String[] args) {
//		testCase1();
//		testCase2();
//		testCase3();
//		testCase4();
		System.out.println(FileDescriptor.out);
	}
	
	/**
	 * 数据流演示
	 */
	public static void testCase1() {
		DataOutputStream dos = null;
		DataInputStream dis = null;
		try {
			// 写入，为了方便演示，直接写到字节数组
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			//DataOutputStream dos = new DataOutputStream(baos);
			dos = new DataOutputStream(new BufferedOutputStream(baos));// 带缓冲
			dos.writeUTF("编码辛酸泪");
			dos.writeInt(18);
			dos.writeBoolean(false);
			dos.writeChar('联');
			dos.flush();
			byte[] datas = baos.toByteArray();
			
			// 读取，一定要按写入顺序读取
			//DataInputStream dis = new DataInputStream(new ByteArrayInputStream(datas));
			dis = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));// 带缓冲
			String s1 = dis.readUTF();
			int s2 = dis.readInt();
			boolean s3 = dis.readBoolean();
			char s4 = dis.readChar();
			System.out.println(s1);
			System.out.println(s2);
			System.out.println(s3);
			System.out.println(s4);
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				dos.close();
				dis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 对象流演示，对象序列化到字节数组
	 * 
	 */
	public static void testCase2() {
		ObjectOutputStream oos = null;
		ObjectInputStream ois = null;
		try{
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(new BufferedOutputStream(baos));
			// 写入字节数组
			oos.writeUTF("谁知其中味");
			oos.writeInt(18);
			oos.writeBoolean(true);
			oos.writeObject(new Date());
			oos.writeObject(new Employee("Jack Ma", 400));
			oos.flush();
			
			ois = new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())));
			// 读取数据
			System.out.println(ois.readUTF());
			System.out.println(ois.readInt());
			System.out.println(ois.readBoolean());
			
			Object date = ois.readObject();
			Object employee = ois.readObject();
			
			if(date instanceof Date) {
				Date dateObj = (Date)date;
				System.out.println(dateObj);
			}
			if(employee instanceof Employee) {
				Employee empObj = (Employee)employee;
				System.out.println(empObj.getName()+"--->"+empObj.getSalary());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			FileUtil.close(oos, ois);
		}
	}
	
	
	/**
	 * 对象流演示，对象序列化到文件
	 * 
	 */
	public static void testCase3() {
		ObjectInputStream ois = null;
		ObjectOutputStream oos = null;
		try {
			// 写入数据到文件
			oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("files/target/obj.ser")));
			oos.writeUTF("编码辛酸泪，谁知其中味");
			oos.writeInt(18);
			oos.writeBoolean(true);
			oos.writeObject(new Date());
			oos.writeObject(new Employee("小马哥", 350));
			oos.flush();
			
			// 读取文件中数据
			ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream("files/target/obj.ser")));
			System.out.println(ois.readUTF());
			System.out.println(ois.readInt());
			System.out.println(ois.readBoolean());
			
			Object date = ois.readObject();
			Object employee = ois.readObject();
			
			if(date instanceof Date) {
				Date dateObj = (Date)date;
				System.out.println(dateObj);
			}
			if(employee instanceof Employee) {
				Employee empObj = (Employee)employee;
				System.out.println(empObj.getName()+"--->"+empObj.getSalary());
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			FileUtil.close(oos, ois);
		}
	}
	
	
	/**
	 * 打印流
	 * 这个程序ps不停变更指向，会不会结尾只关闭了最后一个流而出现问题？
	 */
	public static void testCase4() {
		PrintStream ps = null;
		try {
			// 可以直接将内容打印到控制台
			ps = System.out;//相当于一个管道直接对接到控制台
			ps.println("打印流");
			ps.println(18);
			
			// 可以将内容打印到文件
			ps = new PrintStream(new BufferedOutputStream(new FileOutputStream("files/target/print.txt")),true);
			ps.println(true);
			ps.println('联');
			ps.println(18);
			
			// 重定向System.out输出到ps指向的文件
			System.setOut(ps);// 相当于将System.out管道从控制台对接到print.txt文件
			System.out.println("changed");
			
			// 接着又将System.out输出端对接到控制台,通过采用系统提供的标准输出文件描述符
			System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));
			System.out.println("I am backed");
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			FileUtil.close(ps);
		}
	}

}



class Employee implements Serializable{
	private static final long serialVersionUID = 1L;
	
	private transient String name;//不需要序列化的对象属性
	private double salary;
	
	public Employee() {
		super();
	}
	public Employee(String name, double salary) {
		super();
		this.name = name;
		this.salary = salary;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
}
